import numpy as np
import math
def sign(x):
    if x>0:
        return 1
    else:
        return -1
def signMat(x):
    maty=[]
    for i in x:
        temp=sign(i)
        maty.append(temp)
    return maty
def H(x,t):
    if x<t:
        return 1
    else:
        return -1
def generatex(X,x0):
    y1=[]
    y2=[]
    for i in X.flat:
        ytemp=H(i,x0)
        y1.append(ytemp)
    for j in X.flat:
        ytemp=H(-j,-x0)
        y2.append(ytemp)
    return y1,y2
def compare(y,y1):
    comresult=[]
    for i in range(len(y1)):
        if y[i]!=y1[i]:
            comresult.append(i)
    return comresult
def calce(X,x0,matw,y):
    temp=generatex(X,x0)
    result1=compare(y,temp[0])
    sum1=0
    for i in range(len(result1)):
        sum1=sum1+matw[result1[i]]
    result2=compare(y,temp[1])
    sum2=0
    for j in range(len(result2)):
        sum2=sum2+matw[result2[j]]
    sum=[sum1,sum2]
    return sum
def findx0(X,y,matw):
    matx0=X-np.ones(len(X))/2
    mate=[]
    for x0 in matx0.flat:
        temp=calce(X,x0,matw,y)
        mate.append(temp)
    min=mate[0][0]
    mini=matx0[0]
    minj=0
    for i in range(len(mate)):
        for j in range(2):
            temp=mate[i][j]
            if temp<min:
                min=temp
                mini=matx0[i]
                minj=j
    return min,mini,minj
def adaboost(X,y,matw,matsum,t):
    if signMat(matsum)==list(y):
        return matsum
    else:
        e=findx0(X,y,matw)[0]
        miu=findx0(X,y,matw)[1]
        pdvalue=findx0(X,y,matw)[-1]
        alpha=math.log((1-e)/e)/2
        z=2*math.sqrt(e*(1-e))
        tempsum=[]
        for i in range(len(matw)):
            matw[i]=matw[i]/z*math.exp(-alpha*H(math.pow(-1,pdvalue)*X[i],math.pow(-1,pdvalue)*miu)*y[i])
            temp=alpha*H(math.pow(-1,pdvalue)*X[i],math.pow(-1,pdvalue)*miu)
            tempsum.append(temp)
        tempsum=np.array(tempsum)
        matsum=matsum+tempsum
        if pdvalue==0:
            t=t+'\n'+str(alpha)+"H"+str(times)+"(x),其中H(x)=1(x<"+str(miu)+"),H(x)=-1(x>"+str(miu)+")"
            print(t)
        return adaboost(X,y,matw,matsum,t)
X=np.array(range(10))
y=np.array([1,1,1,-1,-1,-1,1,1,1,-1])
matw=0.1*np.ones(10)
matsum=np.array(np.zeros(10))
t="f(x)="
times=1
print(signMat(adaboost(X,y,matw,matsum,t)))